package com.slz3.business.module.drawManagement.draIntegralLottery.steward;

import com.slz3.business.frame.enums.AuditFlag;
import com.slz3.business.frame.enums.UsingFlag;
import com.slz3.business.frame.enums.YNFlag;
import com.slz3.business.frame.module.Services;
import com.slz3.business.frame.redis.Jedis;
import com.slz3.business.frame.redis.RK;
import com.slz3.business.frame.response.RR;
import com.slz3.business.frame.response.ResInfo;
import com.slz3.business.frame.steward.Steward;
import com.slz3.business.frame.util.VE;
import com.slz3.business.module.drawManagement.draIntegralLottery.domain.DraIntegralLottery;
import com.slz3.business.module.drawManagement.draIntegralLottery.domain.DraIntegralLotteryFactory;
import org.springframework.data.domain.Page;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

public class DraIntegralLotteryResExecutor {

    static Mono<ServerResponse> add(ServerRequest req, DraIntegralLottery draIntegralLottery) {

        DraIntegralLottery draIntegralLotteryDBLatest = Services.draIntegralLottery.save(draIntegralLottery);
        //创建后  活动开启前 十分钟进行提醒
        String uuid= draIntegralLotteryDBLatest.getUuid().toString();//活动ID
        LocalDateTime createTime = draIntegralLotteryDBLatest.getCreateTime();
        Long second = createTime.toEpochSecond(ZoneOffset.of("+8"))-10*60L-LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8"));
        if(second>0){//活动开启时间距离当前时间 大于十分钟
            Jedis.db0.set(RK.DAW_ACTIVITY_BEFORE_REMIND__$UUID$.replace("${uuid}",uuid),0,second);
            Jedis.db0.set(RK.DAW_ACTIVITY_BEFORE_REMIND__HASH.replace("${uuid}",uuid),Steward.obj2Map(draIntegralLotteryDBLatest));
        }else{
            //活动开启时间  在十分钟之内 不提醒？
        }

        DraIntegralLotteryFactory.saveDraIntegralLotteryNumber(draIntegralLotteryDBLatest);

        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(draIntegralLotteryDBLatest).build());
    }

    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> delete(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLottery.delete(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("delete fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    static Mono<ServerResponse> modify(ServerRequest req, DraIntegralLottery source) {
        DraIntegralLottery target = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (target != null) {
            Steward.merge(source, target);
            if (!isCanModifyEntity(target)) {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("活动已经开始不能修改！").build());
            }
            DraIntegralLottery draIntegralLotteryDBLatest = Services.draIntegralLottery.modify(target);

            UUID uuid = draIntegralLotteryDBLatest.getUuid();

            if (draIntegralLotteryDBLatest.getSerGoodsDrawStartDate().isAfter(LocalDateTime.now())) {
                Jedis.db0.remove(String.format("%s:%s:%s:%s", RK.CONFIG_DOMIN, RK.DRA_INTEGRAL_LOTTERY, RK.NUMBER, uuid));

                DraIntegralLotteryFactory.saveDraIntegralLotteryNumber(draIntegralLotteryDBLatest);
            }



            //查找中奖人
            List<Map> listStartEnd = Jedis.db0.getListStartEnd(String.format("%s:%s:%s:%s:%s:%s:%s", RK.BUSSINES, RK.DRAW, RK.DRA_INTEGRAL_LOTTERY, RK.DRAW_ITEM, RK.PARTAKE, uuid.toString(), RK.DATA_MAP), 0, 100);

            Map<String, Object> userDraw = new HashMap<>();
            Map<String, Object> userDraw2 = new HashMap<>();
            listStartEnd.stream().forEach(fieldMap -> {
                if (fieldMap.get("number").equals(draIntegralLotteryDBLatest.getSerGoodsDrawNumber())) {
                    //向 积分抽奖 中奖历史表添加数据
                    userDraw.put("drawId", uuid.toString());
                    userDraw.put("number", fieldMap.get("number"));
                    userDraw.put("termOfValidity", "");//Term of validity有效期 TODO
                    userDraw.put("serGoodsDrawPname", draIntegralLotteryDBLatest.getSerGoodsDrawPname());
                    userDraw.put("serGoodsDrawP2", draIntegralLotteryDBLatest.getSerGoodsDrawP2());
                    userDraw.put("status", 1); //1未领取 2已领取
                    userDraw.put("drawType", 4); //3免费  4积分
                    userDraw.put("serJiFenOrTicket", fieldMap.get("serGoodsDrawJiFen")); //积分或者券
                    userDraw.put("serGoodsDrawPrice", fieldMap.get("serGoodsDrawPrice")); //价值
                    userDraw.put("createTimeStamp", fieldMap.get("createTimeStamp"));
                    // 某会员都中过什么抽奖商品  业务:抽奖:免费:会员:中奖:会员id:DataMap   map:<商品id, 抽奖号码>
                    Jedis.db0.rpush(String.format("%s:%s:%s:%s:%s:%s:%s", RK.BUSSINES, RK.DRAW, RK.DRA_INTEGRAL_LOTTERY, RK.USER_MEMBER, RK.WINNER, fieldMap.get("userId"), RK.DATA_MAP), userDraw);
                    userDraw2.put("number", fieldMap.get("number"));
                    userDraw2.put("userId", fieldMap.get("userId"));
                    userDraw2.put("termOfValidity", "");//Term of validity有效期 TODO
                    userDraw2.put("serGoodsDrawPname", draIntegralLotteryDBLatest.getSerGoodsDrawPname());
                    userDraw2.put("serGoodsDrawP2", draIntegralLotteryDBLatest.getSerGoodsDrawP2());
                    userDraw2.put("status", 1); //1未领取 2已领取
                    userDraw2.put("drawType", 4); //3免费  4积分
                    userDraw2.put("serJiFenOrTicket", fieldMap.get("serGoodsDrawJiFen")); //积分或者券
                    userDraw2.put("serGoodsDrawPrice", fieldMap.get("serGoodsDrawPrice")); //价值
                    userDraw2.put("createTimeStamp", fieldMap.get("createTimeStamp"));
                    // 某抽奖商品都有哪些会员中奖了      业务:抽奖:免费:商品:中奖:商品id:DataMap    map:<会员id, 抽奖号码>
                    Jedis.db0.rpush(String.format("%s:%s:%s:%s:%s:%s:%s", RK.BUSSINES, RK.DRAW, RK.DRA_INTEGRAL_LOTTERY, RK.DRAW_ITEM, RK.WINNER, uuid.toString(), RK.DATA_MAP), userDraw2);
                }
            });
            return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(draIntegralLotteryDBLatest).build());
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    static Mono<ServerResponse> list(ServerRequest req) {
        Page<DraIntegralLottery> draIntegralLotteryPage = Services.draIntegralLottery.page(req.queryParams());
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).theme("page").page(draIntegralLotteryPage).build());
    }

    static Mono<ServerResponse> info(ServerRequest req) {
        DraIntegralLottery target = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (target != null) {
            return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domain(target).build());
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    static Mono<ServerResponse> choice(ServerRequest req) {
        Page<DraIntegralLottery> draIntegralLotteryPage = Services.draIntegralLottery.page(req.queryParams());
        return RR.success(req, ResInfo.builder().code(RR.SUCCESS).theme("page").page(draIntegralLotteryPage).build());
    }

    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> auditSubmit(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            draIntegralLotteryList.stream().forEach(item -> {
                item.setSerAudit(AuditFlag.WAIT_AUDIT);
                DraIntegralLotteryFactory.initBaseFields(item);
            });
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLotteryTransactional.batchModify(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditSubmit fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> audit(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            draIntegralLotteryList.stream().forEach(item -> {
                item.setSerAudit(AuditFlag.APPROVED);
                DraIntegralLotteryFactory.initBaseFields(item);
            });
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLotteryTransactional.batchModify(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("audit fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> auditReject(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            draIntegralLotteryList.stream().forEach(item -> {
                item.setSerAudit(AuditFlag.REJECT);
                DraIntegralLotteryFactory.initBaseFields(item);
            });
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLotteryTransactional.batchModify(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditReject fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }

    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> usingEnable(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            draIntegralLotteryList.stream().forEach(item -> {
                item.setSerUsing(UsingFlag.ENABLE);
                DraIntegralLotteryFactory.initBaseFields(item);
            });
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLotteryTransactional.batchModify(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("auditReject fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }


    /**
     * known: draIntegralLotteryList is not null
     */
    public static Mono<ServerResponse> usingDisable(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            draIntegralLotteryList.stream().forEach(item -> {
                item.setSerUsing(UsingFlag.DISABLE);
                DraIntegralLotteryFactory.initBaseFields(item);
            });
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLotteryTransactional.batchModify(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("usingDisable fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }
    public static Mono<ServerResponse> lottery(ServerRequest req) {
        List<DraIntegralLottery> draIntegralLotteryList = RR.attribute(req, RR.RELAY_SAFE_VALID);
        if (VE.isNotEmpty(draIntegralLotteryList)) {
            List<DraIntegralLottery> draIntegralLotteryListNew = Services.draIntegralLottery.lottery(draIntegralLotteryList);
            if (VE.isNotEmpty(draIntegralLotteryListNew) && draIntegralLotteryListNew.size() == draIntegralLotteryList.size()) {
                return RR.success(req, ResInfo.builder().code(RR.SUCCESS).domains(draIntegralLotteryListNew).build());
            } else {
                return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("lottery fail").build());
            }
        } else {
            return RR.fail(req, ResInfo.builder().code(RR.EXECUTOR).theme("cannot find entity").build());
        }
    }
    /**
     * 判断是否能够修改 不能修改条件如下：
     * 1  判断当前时间大于开始时间就不能修改 （ 当前时间 < 开始时间 < 结束时间 ）
     * 2. 已经开奖
     *
     * @param lottery
     * @return 【可以修改：true,不可以修改：false】
     */
    private static Boolean isCanModifyEntity(DraIntegralLottery lottery) {
        LocalDateTime localDateTime = LocalDateTime.now();
        if ((localDateTime.isBefore(lottery.getSerGoodsDrawStartDate()) && localDateTime.isAfter(lottery.getSerGoodsDrawEndDate())) || YNFlag.YES.equals(lottery.getSerAlreadyLotteryEnum())) {
            return false;
        }
        return true;
    }
}
